<?php

namespace Portal\Common;

use Portal\Domain\Admin as AdminDomain;
use PhalApi\Exception\BadRequestException;

/**
 * 管理员会话服务
 * @author chenwengen 20240422
 */
class Admin
{
    // 管理员ID
    protected $id;

    // 管理员账号
    protected $username;

    // 管理员角色
    protected $roles;

    protected $deptId;

    protected $roleIds;
    //用户过期时间
    public $exp;

    // const SESSION_KEY = 'phalapi_Portal';

    public function __construct()
    {
        //记录日志

    }

    /**
     * 管理员成功登录，开启会话
     */
    // public function login($id, $username, $role)
    // {
    //     // $_SESSION[self::SESSION_KEY] = array(
    //     //     'id' => $id,
    //     //     'username' => $username,
    //     //     'role' => $role,
    //     // );
    // }

    /**
     * 退出登录，清除会话
     */
    public function logout()
    {
        // $_SESSION[self::SESSION_KEY] = array();
    }

    /**
     * 检测是否登录
     */
    public function check()
    {
        # 1. 从 Authorization 头中获取 token

        $bearerToken = \PhalApi\DI()->request->getHeader('Authorization');
        if (isset($bearerToken) && substr($bearerToken, 0, 7) == 'Bearer ') {
            $token = str_replace('Bearer ', '', $bearerToken);
            \PhalApi\DI()->logger->debug('token:'.$token);
        } else {
            throw new BadRequestException('Authorization Required!', 3);
        }
        $token = trim($token);
        //检测是token是否在黑名单中，如果是提示 Token revoked
        $checkToken = \PhalApi\DI()->cache->get('blacklist_'.$token);
        if ($checkToken) {
            throw new BadRequestException('Token revoked!', 3);
        }
        try {
            # 2. 解析 token 获取用户 ID
            $payload = \PhalApi\DI()->jwt->decodeJwtByParam($token);
            \PhalApi\DI()->logger->info(json_encode($payload));
            $this->id = $payload['id'];
            $this->roles = $payload['roles'];
            $this->username = $payload['username'];
            $this->roleIds = $payload['role_ids'];
            $this->exp = $payload['exp'];
        } catch (\Exception $e) {
            throw new BadRequestException($e->getMessage(), 1);
        }
        # 3. 获取用户信息和用户的角色列表
        //检查用户是否已经删除
        $adminDomain = new AdminDomain();
        $adminData = $adminDomain->getInfo($this->id);
        if (!$adminData) {
            throw new BadRequestException('用户不存在', 3);
        }
        if ($adminData['is_deleted'] == "1" || $adminData['status'] == "0") {
            throw new BadRequestException('用户已禁用或删除', 3);
        }
        //赋值部门id
        $this->deptId = $adminData['dept_id'];
        // # 如果是root用户，直接放行，不需要验证权限
        // if ($this->isRoot()) {
        //     return true;
        // } else {
        //     if (!$this->roles) {
        //         throw new BadRequestException('用户未分配任何角色', 3);
        //     }
        //     //判断权限

        // }

    }
    /**
    //检查权限
    权限验证装饰器
    :param perms_list: 权限标识列表，如 ["sys:user:add", "sys:user:edit"]
    :return: 如果用户拥有所有指定权限则允许访问，否则返回无权限提示
    */
    public function permissionRequired($permsList)
    {
        if ($this->isRoot() || empty($permsList)) {
            return true;
        }
        $adminDomain = new AdminDomain();
        $adminData = $adminDomain->getInfo($this->id);
        $currentPerms = $adminData['perms'];
        if (empty($currentPerms)) {
            throw new BadRequestException('请求的权限不存在', 3);
        }
        foreach ($permsList as $list) {
            //查询当前权限是否存在
            if (!in_array($list, $currentPerms)) {
                throw new BadRequestException("请求的权限".$list."不存在", 3);
            }
        }
    }
    /**
       数据权限验证函数
    Role模型中的data_scope字段说明：1-所有数据 2-本部门及子部门数据 3-本部门数据 4-本人数据

    支持两种模式:
    1. 操作权限验证模式: 验证当前用户是否有权限操作指定用户的数据
       传入参数: token, operation(add/update/delete中的一个), target_user_id(被操作的用户ID)
       返回值: True/False 表示是否有权限

    2. 查询范围模式: 获取当前用户可以查看的用户ID范围
       传入参数: token, operation="select"
       返回值: "all" 或 用户ID列表

    :param token: 用户令牌
    :param operation: 操作类型，可以是"add", "update", "delete", "select"
    :param target_user_id: 被操作的用户ID，仅在操作权限验证模式下需要

     */
    public function dataPermissionRequired($operation, $targetUserId)
    {
        #查询所有角色的data_scope
        if (empty($this->roles)) {
            throw new BadRequestException('角色不存在', 3);
        }
        # 2. 获取最小的data_scope值（最高权限）
        $roleDomain = new \Portal\Domain\Role();
        $minDataScope = $roleDomain->minDataScope($this->roles);
        # 3. 根据data_scope和操作类型进行权限验证
        if ($operation == "select") {
            if ($this->isRoot()) {
                return "all";
            }
            $deptDomain = new \Portal\Domain\Dept();
            $userIds = $deptDomain->getViewableUserIds($this->id, $this->deptId, $minDataScope);
            return $userIds;
        } elseif (in_array($operation, ['add','update','delete'])) {
            # 1. 如果是超级管理员，直接返回最高权限
            if ($this->isRoot()) {
                return true;
            }
            if ($targetUserId == "0") {
                throw new BadRequestException('数据权限验证错误：未提供目标用户ID', 3);
            }
            $deptDomain = new \Portal\Domain\Dept();
            return  $deptDomain->hasPermissionToOperation($this->id, $this->deptId, $minDataScope, $targetUserId);
        } else {
            throw new BadRequestException('数据权限验证错误：不支持的操作类型'.$operation, 3);

        }



    }

    /**
     * 是否为超级管理员
     * @return boolean
     */
    public function isRoot()
    {
        return in_array('ROOT', $this->roles);
    }

    /**
     * 是否为游客
     * @return boolean
     */
    // public function isGuest()
    // {
    //     // return $this->check(false);
    // }

    // public function __get($name)
    // {
    //     // return isset($_SESSION[self::SESSION_KEY][$name]) ? $_SESSION[self::SESSION_KEY][$name] : null;
    // }
    //获取管理员id
    public function getId()
    {
        return $this->id;
    }
    //获取管理员角色
    public function getRoles()
    {
        return $this->roles;
    }
    //获取管理员用户名
    public function getUserName()
    {
        return $this->username;
    }
    public function getRoleIds()
    {
        return $this->roleIds;
    }
}
